Welcome to the ATFS (Alliance for Tropical Research Science) data harmonization app!

1 Intro

The app is a tool meant to be used by 2 or more networks that are planing on combining their data for a common analysis.

1.1 Profiles

The app relies on “Profiles” that indicate how the data is stored in the file(s) provided: names of columns storing the DBH, the census ID, the tree tag, units of measurements etc…

A profile is a .rds file that is downloaded via the app once all the information about the data has been provided in the Headers and Units tab of the app.

One same profile can be uploaded as “input profile” in the Headers and Units tab, to speed up the process once your network’s data has been profiled, and/or as “output profile” in the Output format tab, to transform other networks’ data into that profile.

Some networks have their profile stored within the app.

1.2 Getting your data ready

The app only accepts CSV files.

It performs best if all the information that you want to share is collated into one analytical file, so we recommend that you append your species and plot information to your measurement information beforehand, and upload that one bigger file into the app.

That said, you can decide to utilize the app to do exactly that. There is no limit to the number of files you can upload but they all need to connect to each other in one way or another, so that by a stacking and/or merging them, it is possible to collate them down to one file. We will get to this in more detail in a moment.

The app also relied on tidy data, which means that every column is a variable, every row is an observation and every cell is a single value. For example, a data set with multiple column for the DBH measurement (e.g. DBH_2015, DBH_2020 etc…) is not a tidy data set. Instead, there should be a column for the variable year (which, in our example, will take a value of 2015 or 2020), and a column for DBH. If your data is not in a tidy format, the Tidy table tab will help you reshape your data.

1.3 R package

The app relies on functions that are maintained in a GitHub R package located here: https://github.com/Alliance-for-Tropical-Forest-Science/DataHarmonization.

1.4 Getting the app to start

1.4.1 Running the app on your local machine

We recommend to run the app on your local machine (via R and RStudio) if one of the following cases apply to you:

  • You have poor internet connection
  • You are working with large data files
  • You are familiar with the development of Shiny apps and would like to troubleshoot any issues you may encounter yourself

To open the app in R, you will need to install the DataHarmonization R package and launch Shiny with the following lines of code.

# install the R package

devtools::install_github("Alliance-for-Tropical-Forest-Science/DataHarmonization", build_vignettes = TRUE)

# run the app

shiny::runGitHub( "Alliance-for-Tropical-Forest-Science/DataHarmonization", subdir = "inst/app")

Note that you may need to install devtools package first and that installing the DataHarmonization R package may ask you to update a list packages.

You’ll want to re-install the package every once in a while, to get the latest version of the app.

1.4.2 Running the app online

If you don’t have R and RStudio and if your data is not too big, you can choose to run the online version of the app by clicking on this link. Note that online version may be lagging behind the GitHub version.

2 Interacting with the app

Once the app is launched you can start interacting with it.

There are multiple tabs to go through. Some tabs will be skipped automatically if they don’t apply to your situation and you may skip others if you don’t need/want them.

When you land on a tab, always advance with an action button (even if skipping) so your inputs are taken into account. You may use the navigation panel to return to a previous tab but remember to click on an action button to save your updated entries.

2.1 Upload your file(s)

This tab starts with information that we already covered in the intro. The checklist is only a guideline to help you getting ready, and you don’t actually need to check the boxes to keep going.

The numbered tasks are the elements that you do need to complete to be able to move forward.

  1. Indicate how many tables you wish to upload

  2. Indicate the finest level of measurement in your data:

    • Plot: if your data only consists of plot level measurements like species richness, total basal area, total number of stems etc…
    • Species: if your data consists of species level measurements like abundance, basal area etc… This does not prevent you from uploading plot level information if, e.g. the area of the plots in which you measured species-level abundance are stored in a separate file.
    • Tree: if your data consists of tree diameters, circumference,… and you are only measuring the main stem of each tree. This does not prevent you from uploading plot and species level information if, e.g. the area of the plots in which you measured your trees, and the Latin names of the species they belonged too are stored in a separate file.
    • stem: if your data consists of stem diameters, circumference,… and you may have multiple stems belonging to a same tree. This does not prevent you from uploading plot and species level information if, e.g. the area of the plots in which you measured your trees, and the Latin names of the species they belonged too are stored in a separate file.

Again, even if you are uploading plot level information, if you have a stem level data, you should upload that file along and indicate that your level of measurement is “Stem”.

  1. Upload you tables. You’ll have as meany upload boxes as you indicated needing in step 1. For each of them:

    • click on Browse... and navigate to the csv file you want to upload
    • Type a more meaningful name to replace the generic “Table1”, “Table2” etc… This is particularly useful if you are uploading more than one fileh
    • check on the right hand side that the columns and rows of your data are rendering properly.
    • In the unlickely event that your tables are not rendering properly, adjust the parameters (separator and header) by clicking on the little gear icon .

Click on SUBMIT to proceed to the next step.

2.2 Stack tables

If you uploaded more than one table, you will be prompted to the Stack tables tab, but thid tab will be skipped if you only uploaded one table.

You will need to stack 2 or more tables if you are collecting the same information in multiple files. This can be the case if, for example, you are keeping your measurements from different plots in different files. Or you are keeping one file per census.

It is important that the files you are stacking have the same set of columns.

2.3 Merge tables

2.4 Tidy table

2.5 Headers and Units

2.6 Codes

2.7 Corrections

2.8 Output format

2.9 Visualise results

2.10 Download

2.11 Help

LS0tCnRpdGxlOiAiRGF0YSBIYXJtb25pemF0aW9uIEFwcCBUdXRvcmlhbCIKZGF0ZTogImByIGZvcm1hdChTeXMudGltZSgpLCAnJVktJW0tJWQnKWAiCm91dHB1dDogCiAgaHRtbF9ub3RlYm9vazoKICAgIGRmX3ByaW50OiBwYWdlZAogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCi0tLQoKYGBge3IgaW5jbHVkZT1GQUxTRX0KbGlicmFyeShmb250YXdlc29tZSkKYGBgIAoKCgoKV2VsY29tZSB0byB0aGUgQVRGUyAoQWxsaWFuY2UgZm9yIFRyb3BpY2FsIFJlc2VhcmNoIFNjaWVuY2UpIGRhdGEgaGFybW9uaXphdGlvbiBhcHAhCgoKIyBJbnRybyB7I2ludHJvfQoKVGhlIGFwcCBpcyBhIHRvb2wgbWVhbnQgdG8gYmUgdXNlZCBieSAyIG9yIG1vcmUgbmV0d29ya3MgdGhhdCBhcmUgcGxhbmluZyBvbiBjb21iaW5pbmcgdGhlaXIgZGF0YSBmb3IgYSBjb21tb24gYW5hbHlzaXMuCgojIyBQcm9maWxlcyB7I3Byb2ZpbGV9CgpUaGUgYXBwIHJlbGllcyBvbiAiUHJvZmlsZXMiIHRoYXQgaW5kaWNhdGUgaG93IHRoZSBkYXRhIGlzIHN0b3JlZCBpbiB0aGUgZmlsZShzKSBwcm92aWRlZDogbmFtZXMgb2YgY29sdW1ucyBzdG9yaW5nIHRoZSBEQkgsIHRoZSBjZW5zdXMgSUQsIHRoZSB0cmVlIHRhZywgdW5pdHMgb2YgbWVhc3VyZW1lbnRzIGV0Yy4uLgoKQSBwcm9maWxlIGlzIGEgLnJkcyBmaWxlIHRoYXQgaXMgZG93bmxvYWRlZCB2aWEgdGhlIGFwcCBvbmNlIGFsbCB0aGUgaW5mb3JtYXRpb24gYWJvdXQgdGhlIGRhdGEgaGFzIGJlZW4gcHJvdmlkZWQgaW4gdGhlIFtgSGVhZGVycyBhbmQgVW5pdHNgXSgjSGVhZGVycykgdGFiIG9mIHRoZSBhcHAuCgpPbmUgc2FtZSBwcm9maWxlIGNhbiBiZSB1cGxvYWRlZCBhcyAiaW5wdXQgcHJvZmlsZSIgaW4gdGhlIFtgSGVhZGVycyBhbmQgVW5pdHNgXSgjSGVhZGVycykgdGFiLCB0byBzcGVlZCB1cCB0aGUgcHJvY2VzcyBvbmNlIHlvdXIgbmV0d29yaydzIGRhdGEgaGFzIGJlZW4gcHJvZmlsZWQsIGFuZC9vciBhcyAib3V0cHV0IHByb2ZpbGUiIGluIHRoZSBbYE91dHB1dCBmb3JtYXRgXSgjT3V0cHV0Rm9ybWF0KSB0YWIsIHRvIHRyYW5zZm9ybSBvdGhlciBuZXR3b3JrcycgZGF0YSBpbnRvIHRoYXQgcHJvZmlsZS4KClNvbWUgbmV0d29ya3MgaGF2ZSB0aGVpciBwcm9maWxlIHN0b3JlZCB3aXRoaW4gdGhlIGFwcC4KCiMjIEdldHRpbmcgeW91ciBkYXRhIHJlYWR5IHsjcHJlcGRhdGF9CgpUaGUgYXBwIG9ubHkgYWNjZXB0cyBDU1YgZmlsZXMuIAoKSXQgcGVyZm9ybXMgYmVzdCBpZiBhbGwgdGhlIGluZm9ybWF0aW9uIHRoYXQgeW91IHdhbnQgdG8gc2hhcmUgaXMgY29sbGF0ZWQgaW50byBvbmUgYW5hbHl0aWNhbCBmaWxlLCBzbyB3ZSByZWNvbW1lbmQgdGhhdCB5b3UgYXBwZW5kIHlvdXIgc3BlY2llcyBhbmQgcGxvdCBpbmZvcm1hdGlvbiB0byB5b3VyIG1lYXN1cmVtZW50IGluZm9ybWF0aW9uIGJlZm9yZWhhbmQsIGFuZCB1cGxvYWQgdGhhdCBvbmUgYmlnZ2VyIGZpbGUgaW50byB0aGUgYXBwLgoKVGhhdCBzYWlkLCB5b3UgY2FuIGRlY2lkZSB0byB1dGlsaXplIHRoZSBhcHAgdG8gZG8gZXhhY3RseSB0aGF0LiBUaGVyZSBpcyBubyBsaW1pdCB0byB0aGUgbnVtYmVyIG9mIGZpbGVzIHlvdSBjYW4gdXBsb2FkIGJ1dCB0aGV5IGFsbCBuZWVkIHRvIGNvbm5lY3QgdG8gZWFjaCBvdGhlciBpbiBvbmUgd2F5IG9yIGFub3RoZXIsIHNvIHRoYXQgYnkgYSBzdGFja2luZyBhbmQvb3IgbWVyZ2luZyB0aGVtLCBpdCBpcyBwb3NzaWJsZSB0byBjb2xsYXRlIHRoZW0gZG93biB0byBvbmUgZmlsZS4gV2Ugd2lsbCBnZXQgdG8gdGhpcyBpbiBtb3JlIGRldGFpbCBpbiBhIG1vbWVudC4KClRoZSBhcHAgYWxzbyByZWxpZWQgb24gW3RpZHldKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy90aWR5ci92aWduZXR0ZXMvdGlkeS1kYXRhLmh0bWwjOn46dGV4dD1UaWR5JTIwZGF0YSUyMGlzJTIwYSUyMHN0YW5kYXJkLEV2ZXJ5JTIwY29sdW1uJTIwaXMlMjBhJTIwdmFyaWFibGUuKSBkYXRhLCB3aGljaCBtZWFucyB0aGF0IGV2ZXJ5IGNvbHVtbiBpcyBhIHZhcmlhYmxlLCBldmVyeSByb3cgaXMgYW4gb2JzZXJ2YXRpb24gYW5kIGV2ZXJ5IGNlbGwgaXMgYSBzaW5nbGUgdmFsdWUuIEZvciBleGFtcGxlLCBhIGRhdGEgc2V0IHdpdGggbXVsdGlwbGUgY29sdW1uIGZvciB0aGUgREJIIG1lYXN1cmVtZW50IChlLmcuIERCSF8yMDE1LCBEQkhfMjAyMCBldGMuLi4pIGlzIG5vdCBhIHRpZHkgZGF0YSBzZXQuIEluc3RlYWQsIHRoZXJlIHNob3VsZCBiZSBhIGNvbHVtbiBmb3IgdGhlIHZhcmlhYmxlIGB5ZWFyYCAod2hpY2gsIGluIG91ciBleGFtcGxlLCB3aWxsIHRha2UgYSB2YWx1ZSBvZiAyMDE1IG9yIDIwMjApLCBhbmQgYSBjb2x1bW4gZm9yIGBEQkhgLgpJZiB5b3VyIGRhdGEgaXMgbm90IGluIGEgdGlkeSBmb3JtYXQsIHRoZSBbYFRpZHkgdGFibGVgXSgjVGlkeWluZykgdGFiIHdpbGwgaGVscCB5b3UgcmVzaGFwZSB5b3VyIGRhdGEuIAoKCiMjIFIgcGFja2FnZSB7I3BhY2thZ2V9CgpUaGUgYXBwIHJlbGllcyBvbiBmdW5jdGlvbnMgdGhhdCBhcmUgbWFpbnRhaW5lZCBpbiBhIEdpdEh1YiBSIHBhY2thZ2UgbG9jYXRlZCBoZXJlOiBodHRwczovL2dpdGh1Yi5jb20vQWxsaWFuY2UtZm9yLVRyb3BpY2FsLUZvcmVzdC1TY2llbmNlL0RhdGFIYXJtb25pemF0aW9uLgoKIyMgR2V0dGluZyB0aGUgYXBwIHRvIHN0YXJ0IHsjc3RhcnR9CgojIyMgUnVubmluZyB0aGUgYXBwIG9uIHlvdXIgbG9jYWwgbWFjaGluZSB7I2xvY2FsUnVufQoKV2UgcmVjb21tZW5kIHRvIHJ1biB0aGUgYXBwIG9uIHlvdXIgbG9jYWwgbWFjaGluZSAodmlhIFIgYW5kIFJTdHVkaW8pIGlmIG9uZSBvZiB0aGUgZm9sbG93aW5nIGNhc2VzIGFwcGx5IHRvIHlvdToKCiAtIFlvdSBoYXZlIHBvb3IgaW50ZXJuZXQgY29ubmVjdGlvbgogLSBZb3UgYXJlIHdvcmtpbmcgd2l0aCBsYXJnZSBkYXRhIGZpbGVzCiAtIFlvdSBhcmUgZmFtaWxpYXIgd2l0aCB0aGUgZGV2ZWxvcG1lbnQgb2YgU2hpbnkgYXBwcyBhbmQgd291bGQgbGlrZSB0byB0cm91Ymxlc2hvb3QgYW55IGlzc3VlcyB5b3UgbWF5IGVuY291bnRlciB5b3Vyc2VsZgogClRvIG9wZW4gdGhlIGFwcCBpbiBSLCB5b3Ugd2lsbCBuZWVkIHRvIGluc3RhbGwgdGhlIERhdGFIYXJtb25pemF0aW9uIFIgcGFja2FnZSBhbmQgbGF1bmNoIFNoaW55IHdpdGggdGhlIGZvbGxvd2luZyBsaW5lcyBvZiBjb2RlLgoKYGBge3J9CiMgaW5zdGFsbCB0aGUgUiBwYWNrYWdlCgpkZXZ0b29sczo6aW5zdGFsbF9naXRodWIoIkFsbGlhbmNlLWZvci1Ucm9waWNhbC1Gb3Jlc3QtU2NpZW5jZS9EYXRhSGFybW9uaXphdGlvbiIsIGJ1aWxkX3ZpZ25ldHRlcyA9IFRSVUUpCgojIHJ1biB0aGUgYXBwCgpzaGlueTo6cnVuR2l0SHViKCAiQWxsaWFuY2UtZm9yLVRyb3BpY2FsLUZvcmVzdC1TY2llbmNlL0RhdGFIYXJtb25pemF0aW9uIiwgc3ViZGlyID0gImluc3QvYXBwIikKYGBgCgpOb3RlIHRoYXQgeW91IG1heSBuZWVkIHRvIGluc3RhbGwgYGRldnRvb2xzYCBwYWNrYWdlIGZpcnN0IGFuZCB0aGF0IGluc3RhbGxpbmcgdGhlIERhdGFIYXJtb25pemF0aW9uIFIgcGFja2FnZSBtYXkgYXNrIHlvdSB0byB1cGRhdGUgYSBsaXN0IHBhY2thZ2VzLgoKKipZb3UnbGwgd2FudCB0byByZS1pbnN0YWxsIHRoZSBwYWNrYWdlIGV2ZXJ5IG9uY2UgaW4gYSB3aGlsZSwgdG8gZ2V0IHRoZSBsYXRlc3QgdmVyc2lvbiBvZiB0aGUgYXBwLioqCgojIyMgUnVubmluZyB0aGUgYXBwIG9ubGluZSB7I29ubGluZVJ1bn0KCklmIHlvdSBkb24ndCBoYXZlIFIgYW5kIFJTdHVkaW8gYW5kIGlmIHlvdXIgZGF0YSBpcyBub3QgdG9vIGJpZywgeW91IGNhbiBjaG9vc2UgdG8gcnVuIHRoZSBvbmxpbmUgdmVyc2lvbiBvZiB0aGUgYXBwIGJ5IGNsaWNraW5nIG9uIHRoaXMgW2xpbmtdKGh0dHBzOi8vdmFsZW50aW5laGVyci5zaGlueWFwcHMuaW8vVG1GT19BY2NlbE5ldC8pLiAKTm90ZSB0aGF0IG9ubGluZSB2ZXJzaW9uIG1heSBiZSBsYWdnaW5nIGJlaGluZCB0aGUgR2l0SHViIHZlcnNpb24uIAoKCiMgSW50ZXJhY3Rpbmcgd2l0aCB0aGUgYXBwIHsjaW50ZXJhY3R9CgpPbmNlIHRoZSBhcHAgaXMgbGF1bmNoZWQgeW91IGNhbiBzdGFydCBpbnRlcmFjdGluZyB3aXRoIGl0LgoKVGhlcmUgYXJlIG11bHRpcGxlIHRhYnMgdG8gZ28gdGhyb3VnaC4gClNvbWUgdGFicyB3aWxsIGJlIHNraXBwZWQgYXV0b21hdGljYWxseSBpZiB0aGV5IGRvbid0IGFwcGx5IHRvIHlvdXIgc2l0dWF0aW9uIGFuZCB5b3UgbWF5IHNraXAgb3RoZXJzIGlmIHlvdSBkb24ndCBuZWVkL3dhbnQgdGhlbS4KCldoZW4geW91IGxhbmQgb24gYSB0YWIsICoqYWx3YXlzIGFkdmFuY2Ugd2l0aCBhbiBhY3Rpb24gYnV0dG9uIChldmVuIGlmIHNraXBwaW5nKSBzbyB5b3VyIGlucHV0cyBhcmUgdGFrZW4gaW50byBhY2NvdW50KiouIFlvdSBtYXkgdXNlIHRoZSBuYXZpZ2F0aW9uIHBhbmVsIHRvIHJldHVybiB0byBhIHByZXZpb3VzIHRhYiBidXQgcmVtZW1iZXIgdG8gY2xpY2sgb24gYW4gYWN0aW9uIGJ1dHRvbiB0byBzYXZlIHlvdXIgdXBkYXRlZCBlbnRyaWVzLgoKCgojIyBVcGxvYWQgeW91ciBmaWxlKHMpIHsjdXBsb2FkfQoKVGhpcyB0YWIgc3RhcnRzIHdpdGggaW5mb3JtYXRpb24gdGhhdCB3ZSBhbHJlYWR5IGNvdmVyZWQgaW4gdGhlIFtpbnRyb10oI2ludHJvKS4gVGhlIGNoZWNrbGlzdCBpcyBvbmx5IGEgZ3VpZGVsaW5lIHRvIGhlbHAgeW91IGdldHRpbmcgcmVhZHksIGFuZCB5b3UgZG9uJ3QgYWN0dWFsbHkgbmVlZCB0byBjaGVjayB0aGUgYm94ZXMgdG8ga2VlcCBnb2luZy4KClRoZSBudW1iZXJlZCB0YXNrcyBhcmUgdGhlIGVsZW1lbnRzIHRoYXQgeW91IGRvIG5lZWQgdG8gY29tcGxldGUgdG8gYmUgYWJsZSB0byBtb3ZlIGZvcndhcmQuCgogMS4gSW5kaWNhdGUgaG93IG1hbnkgdGFibGVzIHlvdSB3aXNoIHRvIHVwbG9hZAogMi4gSW5kaWNhdGUgdGhlIGZpbmVzdCBsZXZlbCBvZiBtZWFzdXJlbWVudCBpbiB5b3VyIGRhdGE6CiAKICAgIC0gUGxvdDogaWYgeW91ciBkYXRhIG9ubHkgY29uc2lzdHMgb2YgcGxvdCBsZXZlbCBtZWFzdXJlbWVudHMgbGlrZSBzcGVjaWVzIHJpY2huZXNzLCB0b3RhbCBiYXNhbCBhcmVhLCB0b3RhbCBudW1iZXIgb2Ygc3RlbXMgZXRjLi4uCiAgICAtIFNwZWNpZXM6IGlmIHlvdXIgZGF0YSBjb25zaXN0cyBvZiBzcGVjaWVzIGxldmVsIG1lYXN1cmVtZW50cyBsaWtlIGFidW5kYW5jZSwgYmFzYWwgYXJlYSBldGMuLi4gVGhpcyBkb2VzIG5vdCBwcmV2ZW50IHlvdSBmcm9tIHVwbG9hZGluZyBwbG90IGxldmVsIGluZm9ybWF0aW9uIGlmLCBlLmcuIHRoZSBhcmVhIG9mIHRoZSBwbG90cyBpbiB3aGljaCB5b3UgbWVhc3VyZWQgc3BlY2llcy1sZXZlbCBhYnVuZGFuY2UgYXJlIHN0b3JlZCBpbiBhIHNlcGFyYXRlIGZpbGUuCiAgICAtIFRyZWU6IGlmIHlvdXIgZGF0YSBjb25zaXN0cyBvZiB0cmVlIGRpYW1ldGVycywgY2lyY3VtZmVyZW5jZSwuLi4gYW5kIHlvdSBhcmUgb25seSBtZWFzdXJpbmcgdGhlIG1haW4gc3RlbSBvZiBlYWNoIHRyZWUuIFRoaXMgZG9lcyBub3QgcHJldmVudCB5b3UgZnJvbSB1cGxvYWRpbmcgcGxvdCBhbmQgc3BlY2llcyBsZXZlbCBpbmZvcm1hdGlvbiBpZiwgZS5nLiB0aGUgYXJlYSBvZiB0aGUgcGxvdHMgaW4gd2hpY2ggeW91IG1lYXN1cmVkIHlvdXIgdHJlZXMsIGFuZCB0aGUgTGF0aW4gbmFtZXMgb2YgdGhlIHNwZWNpZXMgdGhleSBiZWxvbmdlZCB0b28gYXJlIHN0b3JlZCBpbiBhIHNlcGFyYXRlIGZpbGUuCiAgICAtIHN0ZW06IGlmIHlvdXIgZGF0YSBjb25zaXN0cyBvZiBzdGVtIGRpYW1ldGVycywgY2lyY3VtZmVyZW5jZSwuLi4gYW5kIHlvdSBtYXkgaGF2ZSBtdWx0aXBsZSBzdGVtcyBiZWxvbmdpbmcgdG8gYSBzYW1lIHRyZWUuIFRoaXMgZG9lcyBub3QgcHJldmVudCB5b3UgZnJvbSB1cGxvYWRpbmcgcGxvdCBhbmQgc3BlY2llcyBsZXZlbCBpbmZvcm1hdGlvbiBpZiwgZS5nLiB0aGUgYXJlYSBvZiB0aGUgcGxvdHMgaW4gd2hpY2ggeW91IG1lYXN1cmVkIHlvdXIgdHJlZXMsIGFuZCB0aGUgTGF0aW4gbmFtZXMgb2YgdGhlIHNwZWNpZXMgdGhleSBiZWxvbmdlZCB0b28gYXJlIHN0b3JlZCBpbiBhIHNlcGFyYXRlIGZpbGUuCiAKQWdhaW4sIGV2ZW4gaWYgeW91IGFyZSB1cGxvYWRpbmcgcGxvdCBsZXZlbCBpbmZvcm1hdGlvbiwgaWYgeW91IGhhdmUgYSBzdGVtIGxldmVsIGRhdGEsIHlvdSBzaG91bGQgdXBsb2FkIHRoYXQgZmlsZSBhbG9uZyBhbmQgaW5kaWNhdGUgdGhhdCB5b3VyIGxldmVsIG9mIG1lYXN1cmVtZW50IGlzICJTdGVtIi4KCiAzLiBVcGxvYWQgeW91IHRhYmxlcy4gWW91J2xsIGhhdmUgYXMgbWVhbnkgdXBsb2FkIGJveGVzIGFzIHlvdSBpbmRpY2F0ZWQgbmVlZGluZyBpbiBzdGVwIDEuIEZvciBlYWNoIG9mIHRoZW06CiAKICAgIC0gY2xpY2sgb24gYEJyb3dzZS4uLmAgYW5kIG5hdmlnYXRlIHRvIHRoZSBjc3YgZmlsZSB5b3Ugd2FudCB0byB1cGxvYWQKICAgIC0gVHlwZSBhIG1vcmUgbWVhbmluZ2Z1bCBuYW1lIHRvIHJlcGxhY2UgdGhlIGdlbmVyaWMgIlRhYmxlMSIsICJUYWJsZTIiIGV0Yy4uLiBUaGlzIGlzIHBhcnRpY3VsYXJseSB1c2VmdWwgaWYgeW91IGFyZSB1cGxvYWRpbmcgbW9yZSB0aGFuIG9uZSBmaWxlaAogICAgLSBjaGVjayBvbiB0aGUgcmlnaHQgaGFuZCBzaWRlIHRoYXQgdGhlIGNvbHVtbnMgYW5kIHJvd3Mgb2YgeW91ciBkYXRhIGFyZSByZW5kZXJpbmcgcHJvcGVybHkuIAogICAgLSBJbiB0aGUgdW5saWNrZWx5IGV2ZW50IHRoYXQgeW91ciB0YWJsZXMgYXJlIG5vdCByZW5kZXJpbmcgcHJvcGVybHksIGFkanVzdCB0aGUgcGFyYW1ldGVycyAoc2VwYXJhdG9yIGFuZCBoZWFkZXIpIGJ5IGNsaWNraW5nIG9uIHRoZSBsaXR0bGUgZ2VhciBpY29uIGByIGZhKG5hbWUgPSAiY29nIilgLgoKCioqQ2xpY2sgb24gU1VCTUlUKiogdG8gcHJvY2VlZCB0byB0aGUgbmV4dCBzdGVwLgogICAgIAohW10oVXBsb2FkLmdpZikKCgojIyBTdGFjayB0YWJsZXMgeyNTdGFja2luZ30KCklmIHlvdSB1cGxvYWRlZCBtb3JlIHRoYW4gb25lIHRhYmxlLCB5b3Ugd2lsbCBiZSBwcm9tcHRlZCB0byB0aGUgYFN0YWNrIHRhYmxlc2AgdGFiLCBidXQgdGhpZCB0YWIgd2lsbCBiZSBza2lwcGVkIGlmIHlvdSBvbmx5IHVwbG9hZGVkIG9uZSB0YWJsZS4KCllvdSB3aWxsIG5lZWQgdG8gc3RhY2sgMiBvciBtb3JlIHRhYmxlcyBpZiB5b3UgYXJlIGNvbGxlY3RpbmcgdGhlIHNhbWUgaW5mb3JtYXRpb24gaW4gbXVsdGlwbGUgZmlsZXMuIFRoaXMgY2FuIGJlIHRoZSBjYXNlIGlmLCBmb3IgZXhhbXBsZSwgeW91IGFyZSBrZWVwaW5nIHlvdXIgbWVhc3VyZW1lbnRzIGZyb20gZGlmZmVyZW50IHBsb3RzIGluIGRpZmZlcmVudCBmaWxlcy4gT3IgeW91IGFyZSBrZWVwaW5nIG9uZSBmaWxlIHBlciBjZW5zdXMuCgoqKkl0IGlzIGltcG9ydGFudCB0aGF0IHRoZSBmaWxlcyB5b3UgYXJlIHN0YWNraW5nIGhhdmUgdGhlIHNhbWUgc2V0IG9mIGNvbHVtbnMuKiogCgoKCiFbXShTdGFjay5naWYpCgojIyBNZXJnZSB0YWJsZXMgeyNNZXJnaW5nfQoKIyMgVGlkeSB0YWJsZSB7I1RpZHlpbmd9CgojIyBIZWFkZXJzIGFuZCBVbml0cyB7I0hlYWRlcnN9CgojIyBDb2RlcyB7I0NvZGVzfQoKIyMgQ29ycmVjdGlvbnMgeyNDb3JyZWN0fQoKIyMgT3V0cHV0IGZvcm1hdCB7I091dHB1dEZvcm1hdH0KCiMjIFZpc3VhbGlzZSByZXN1bHRzIHsjVmlzdWFsaXNlfQoKIyMgRG93bmxvYWQgeyNTYXZlfQoKIyMgSGVscCB7I0hlbHB9CgoK